﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;


namespace FirstGame
{
    class Wizard : Sprite
    {
        const string WIZARD_ASSETNAME = "WizardSquare";
        const int START_POSITION_X = 125;
        const int START_POSITION_Y = 245;
        const int WIZARD_MOVEMENT_SPEED = 300;
        const int WIZARD_JUMP_SPEED_MAX = 600;
        const int WIZARD_JUMP_SPEED_MIN = 50;
        const float WIZARD_JUMP_SPEED_SCALING = 0.025f;
        const int WIZARD_JUMP_HEIGTH = 200;        
        const int MOVE_UP = -1;
        const int MOVE_DOWN = 1;
        const int MOVE_LEFT = -1;
        const int MOVE_RIGHT = 1;

        enum State
        {
            Walking,
            Jumping,
            Ducking
        }

        enum JumpingState
        { 
            Rising,
            Falling
        }

        State mCurrentState = State.Walking;
        JumpingState mCurrentJumpingState;

        Vector2 mStartingPosition = Vector2.Zero;
        Vector2 mDirection = Vector2.Zero;
        Vector2 mSpeed = Vector2.Zero;

        KeyboardState mPreviousKeyboardState;


        /// <summary>
        /// Sets position and calls Sprite.LoadContent
        /// </summary>
        /// <param name="theContentManager"></param>
        public void LoadContent(ContentManager theContentManager)
        {
            Position = new Vector2(START_POSITION_X, START_POSITION_Y);
            base.LoadContent(theContentManager, WIZARD_ASSETNAME);
            Source = new Rectangle(0, 0, 200, Source.Height);
        }


        /// <summary>
        /// Update Wizard position
        /// </summary>
        /// <param name="theGameTime"></param>
        public void Update(GameTime theGameTime)
        {
            KeyboardState aCurrentKeyboardState = Keyboard.GetState();

            UpdateMovement(aCurrentKeyboardState);
            UpdateJump(aCurrentKeyboardState);
            UpdateDuck(aCurrentKeyboardState);

            mPreviousKeyboardState = aCurrentKeyboardState;

            base.Update(theGameTime, mSpeed, mDirection);
        }

        
        /// <summary>
        /// Check input and update Wizard movement
        /// </summary>
        /// <param name="aCurrentKeyboardState"></param>
        private void UpdateMovement(KeyboardState aCurrentKeyboardState)
        {
            if (mCurrentState == State.Walking || mCurrentState == State.Jumping)
            {
                //mSpeed = Vector2.Zero;
                mDirection = new Vector2(0, mDirection.Y);

                if (aCurrentKeyboardState.IsKeyDown(Keys.Left) == true)
                {
                    mSpeed.X = WIZARD_MOVEMENT_SPEED;
                    mDirection.X = MOVE_LEFT;
                }
                else if (aCurrentKeyboardState.IsKeyDown(Keys.Right) == true)
                {
                    mSpeed.X = WIZARD_MOVEMENT_SPEED;
                    mDirection.X = MOVE_RIGHT;
                }

                /*if (aCurrentKeyboardState.IsKeyDown(Keys.Up) == true)
                {
                    mSpeed.Y = WIZARD_SPEED;
                    mDirection.Y = MOVE_UP;
                }
                else if (aCurrentKeyboardState.IsKeyDown(Keys.Down) == true)
                {
                    mSpeed.Y = WIZARD_SPEED;
                    mDirection.Y = MOVE_DOWN;
                }*/
            }
        }

        /// <summary>
        /// Check for input and update jump movement
        /// </summary>
        /// <param name="aCurrentKeyboardState"></param>
        private void UpdateJump(KeyboardState aCurrentKeyboardState)
        {
            if (mCurrentState == State.Walking)
            {
                if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == false)
                {
                    mCurrentState = State.Jumping;
                    mCurrentJumpingState = JumpingState.Rising;
                    mStartingPosition = Position;
                    mDirection.Y = MOVE_UP;
                    mSpeed.Y = WIZARD_JUMP_SPEED_MAX;
                }                               
            }

            if (mCurrentState == State.Jumping)
            {
                // If still rising
                if (mCurrentJumpingState == JumpingState.Rising)
                {
                    // If max jumping height is reached, move down
                    if (mStartingPosition.Y - Position.Y > WIZARD_JUMP_HEIGTH)
                    {
                        mDirection.Y = MOVE_DOWN;
                        mCurrentJumpingState = JumpingState.Falling;
                    }
                    else
                    {   // While space is pressed keep rising (but slowing down speed)
                        if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == true && mPreviousKeyboardState.IsKeyDown(Keys.Space) == true)
                        {
                            mSpeed.Y = Math.Max(mSpeed.Y - WIZARD_JUMP_SPEED_SCALING * WIZARD_JUMP_SPEED_MAX, WIZARD_JUMP_SPEED_MIN);
                        }
                        // If space is released start falling
                        else if (aCurrentKeyboardState.IsKeyDown(Keys.Space) == false && mPreviousKeyboardState.IsKeyDown(Keys.Space) == true)
                        {
                            mCurrentJumpingState = JumpingState.Falling;
                            mDirection.Y = MOVE_DOWN;                            
                        }
                    }                    
                }

                if (mCurrentJumpingState == JumpingState.Falling)
                {
                    // If origin position is reached
                    if (Position.Y > mStartingPosition.Y)
                    {
                        Position.Y = mStartingPosition.Y;
                        mCurrentState = State.Walking;
                        mDirection.Y = 0;
                    }
                    else
                    {
                        mSpeed.Y = mSpeed.Y + WIZARD_JUMP_SPEED_SCALING * WIZARD_JUMP_SPEED_MAX;
                    }
                }
            }
        }

        /// <summary>
        /// Check for input and update duck position
        /// </summary>
        /// <param name="aCurrentKeyboardState"></param>
        private void UpdateDuck(KeyboardState aCurrentKeyboardState)
        {
            if (aCurrentKeyboardState.IsKeyDown(Keys.LeftShift) == true)
            {
                if (mCurrentState == State.Walking)
                {
                    mSpeed = Vector2.Zero;
                    mDirection = Vector2.Zero;

                    Source = new Rectangle(200, 0, 200, Source.Height);
                    mCurrentState = State.Ducking;
                }
            }
            else
            {
                if (mCurrentState == State.Ducking)
                {
                    Source = new Rectangle(0, 0, 200, Source.Height);
                    mCurrentState = State.Walking;
                }
            }
        }
    }
}
